package cn.uncode.baas.server.resource;

import java.util.HashMap;
import java.util.Map;

import javax.script.ScriptException;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import cn.uncode.baas.server.database.DBContextHolder;
import cn.uncode.baas.server.exception.AuthorizationException;
import cn.uncode.baas.server.exception.BaseException;
import cn.uncode.baas.server.exception.MethodNotFoundException;
import cn.uncode.baas.server.exception.ValidateException;
import cn.uncode.baas.server.internal.context.RestContextManager;
import cn.uncode.baas.server.utils.WatchUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class BaseResource {
	
	private static final Logger LOG = Logger.getLogger(BaseResource.class);
	
	@ExceptionHandler({NoSuchMethodException.class})
	protected ResponseEntity<Object> handleNoSuchMethodException(NoSuchMethodException e){
		LOG.error("execute script error", e);
		return new ResponseEntity<Object>(buildErrorMsg(e), HttpStatus.INTERNAL_SERVER_ERROR);
	}
	
	@ExceptionHandler({ScriptException.class})
	protected ResponseEntity<Object> handleScriptException(ScriptException e){
		LOG.error("execute script error", e);
		return new ResponseEntity<Object>(buildErrorMsg(e), HttpStatus.INTERNAL_SERVER_ERROR);
	}
	
	@ExceptionHandler({ValidateException.class})
	protected ResponseEntity<Object> handleValidateException(ValidateException e){
		LOG.error("validate error", e);
		return new ResponseEntity<Object>(buildErrorMsg(e), HttpStatus.BAD_REQUEST);
	}
	
	@ExceptionHandler({MethodNotFoundException.class})
	protected ResponseEntity<Object> handleMethodNotFoundException(MethodNotFoundException e){
		LOG.error("validate error", e);
		return new ResponseEntity<Object>(buildErrorMsg(e), HttpStatus.NOT_FOUND);
	}
	
	@ExceptionHandler({Exception.class})
	protected ResponseEntity<Object> handleException(Exception e){
		LOG.error("server error", e);
		return new ResponseEntity<Object>(buildErrorMsg(e), HttpStatus.INTERNAL_SERVER_ERROR);
	}
	
	@ExceptionHandler({AuthorizationException.class})
	protected ResponseEntity<Object> handleAuthorizationException(AuthorizationException e){
		LOG.error("server error", e);
		return new ResponseEntity<Object>(buildErrorMsg(e), HttpStatus.UNAUTHORIZED);
	}
	
	/**
     * init
     * @param bucket
     * @param restName
     * @param option
     * @param version
     * @param tag
     * @param maps
     */
	protected void initContext(String bucket, String restName, String option, String version, String tag,
			Map<String, Object> maps) {
		if(StringUtils.isNotEmpty(restName) && StringUtils.isNotEmpty(option) && StringUtils.isNotEmpty(tag)){
			WatchUtils.start(bucket, restName, option, version, tag);
		}
		if(StringUtils.isNotEmpty(restName)){
			RestContextManager.initBucket(bucket);
		}
	}
	
	protected void initContext(String bucket){
		if(StringUtils.isNotEmpty(bucket)){
			RestContextManager.initBucket(bucket);
			DBContextHolder.setDbType(bucket);
		}
	}
    
    /**
     * @param tag
     */
	protected void clearContext(String tag){
		if(StringUtils.isNotEmpty(tag)){
			WatchUtils.stop(tag);
		}
    }
	
	protected void clearContext(){
		DBContextHolder.clearDbType();
    }

   
    /**
     * get project base path
     * @param request
     * @return
     */
	protected String getBasePath(HttpServletRequest request) {
		//String path = request.getContextPath();
		return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
	}
    
    
	
	
	private Map<String, Object> buildErrorMsg(Exception ex){
		Map<String, Object> msg = new HashMap<String, Object>();
		if(StringUtils.isNotEmpty(ex.getMessage())){
			if(ex instanceof BaseException){
				BaseException bex = (BaseException)ex;
				msg.put("code", bex.getNumber());
			}
			msg.put("error", ex.getMessage());
		}else{
			msg.put("error", ex.toString());
		}
		return msg;
	}
	
	

}
